<?php
/**
 * Ttserver缓存连接类。使用Memcached链接方式
 * @name    CacheTtserver
 * @version	1.1.1
 */
class CacheTtserver {

	/**
	 * 写类别标识
	 */
	const ALONE_TYPE_WRITE = 'write';

	/**
	 * 读类别标识
	 */
	const ALONE_TYPE_READ  = 'read';

	/**
	 * 是否读写分离
	 */
	private $isAlone       = false;

	/**
	 * 缓存端链接
	 */
	private $connection    = null;

	/**
	 * 缓存服务器
	 */
	private $servers       = null;
	
	

	/**
	 * 初始化缓存链接设置
	 */
	protected function initOptions($conn) {
		$conn->setOption(Memcached::OPT_COMPRESSION, false);
		
	}

	/**
	 * 设置缓存服务器
	 */
	public function setServers($servers) {
		$this->servers = $servers;
	}

	/**
	 * 链接缓存端
	 * @param  string $type     链接类别
	 * @return mixed  返回缓存端链接
	 */
	protected function connect($type='') {
		if($this->isAlone) {
			if(empty($type)) $type = CacheTtserver::ALONE_TYPE_READ;
			return $this->_connectAlone($type);
		} else {
			return $this->_connect();
		}
	}

	/**
	 * 链接缓存端--普通模式
	 * @return mixed  返回缓存端链接
	 */
	private function _connect() {
		if(!empty($this->connection)) 
			return $this->connection;
		$this->connection = new Memcached();
		$this->initOptions($this->connection);
		if($this->connection) {
			if($this->servers){
				$servers = $this->servers;
			}else{
				return false;
			}
			if(!is_array($servers)) return false;
			
			foreach($servers as $server) {
				if(empty($server['weight'])) $server['weight'] = 1;
				$this->connection->addServer($server['host'],
						$server['port'],
						$server['weight']
				);
			}
		}
		return $this->connection;
	}

	/**
	 * 链接缓存端--读写分离模式
	 * @param  string $type     链接类别
	 * @return mixed  返回缓存端链接
	 */
	private function _connectAlone($type) {
		if(!empty($this->connection[$type])) 
			return $this->connection[$type];
		$this->connection[$type] = new Memcached();
		$this->initOptions($this->connection[$type]);
		if($this->connection[$type]) {
			$servers = $this->servers[$type];
			if(!is_array($servers)) return false;
			foreach($servers as $server) {
				if(empty($server['weight'])) $server['weight'] = 1;
				$this->connection[$type]->addServer($server['host'],
						$server['port'],
						$server['weight']
				);
			}
		}
		return $this->connection[$type];
	}

	/**
	 * 写缓存
	 * @param  string $key      缓存的key
	 * @param  string $value    缓存的value
	 * @param  int    $duration 缓存时间，以秒为单位
	 * @return bool   如果成功缓存则返回true，否则返回false.
	 */
	public function write($key, $value, $duration) {
		$conn = $this->connect(CacheTtserver::ALONE_TYPE_WRITE);
		if(!$conn){
			$this->getdebug('-3006');
		}
		//echo $key.'<br>';
		return $conn->set($key, serialize($value), $duration);
	}

	/**
	 * 删除缓存
	 * @param  string $key      缓存的key
	 * @return bool   如果成功删除,返回true;
	 *    如果key对应的value不存在或者不能删除，则返回false.
	 */
	public function delete($key) {
		$conn = $this->connect(CacheTtserver::ALONE_TYPE_WRITE);
		if(!$conn){
			$this->getdebug('-3006');
		}
		return $conn->delete($key);
	}
	
	/**
	 * 读缓存
	 * @param  string $key       缓存的key
	 * @return mixed  返回key对应的value，如果结果不存在、过期或者在获取的过程中发生错误，将会返回false. 
	 */
	public function read($key) {
		$conn = $this->connect(CacheTtserver::ALONE_TYPE_READ);
		if(!$conn){
			$this->getdebug('-3006');
		}
		if(is_array($key)) {
			//$r = $conn->getMulti($key);
			foreach ($key as $value) {
				$r[$value] = $conn->get($value);
			}
		} else {
			$r = $conn->get($key);
		}
		
		$result = false;
		if(!empty($r)) {
			$result = array();
			//$this->_debug("CacheTtserver read:");
			//$this->_debug($r);
			if(is_array($r)) {
				//$r = array_map('unserialize',$r);
				foreach ($r as $key => $val) {
					$tmp = unserialize($val);
					$result[$key] = $tmp === false && $val != 'b:0;' ? $r[$key] : $tmp;
				}
			} else {
				//$this->_debug("CacheTtserver read:");
				//$this->_debug($r);
				//$r = unserialize($r);
				$tmp = unserialize($r);
				$result = $tmp === false && $r != 'b:0;' ? $result : $tmp;
			}
			//$r = is_array($r)?array_map('unserialize',$r):unserialize($r);
		}
		return $result;
	}

	/**
	 * 添加缓存。如果已存在值则返回false
	 * @param  string $key      缓存的key
	 * @param  string $value    缓存的value
	 * @param  int    $duration 缓存时间，以秒为单位
	 * @return bool   如果成功缓存则返回true，否则返回false.
	 */
	public function add($key, $value, $duration) {
		$conn = $this->connect(CacheTtserver::ALONE_TYPE_WRITE);
		if(!$conn){
			$this->getdebug('-3006');
		}
		return $conn->add($key, serialize($value), $duration);
	}

	/**
	 * 自增。
	 * @param  string $key      缓存的key
	 * @param  int    $value    缓存的value
	 * @return mixed  返回key对应的value，
	 *    如果结果不存在、过期或者在获取的过程中发生错误，将会返回false. 
	 */
	public function increment($key,$value=1) {
		$conn = $this->connect(CacheTtserver::ALONE_TYPE_WRITE);
		if(!$conn){
			$this->getdebug('-3006');
		}
		return $conn->increment($key, $value);
	}

	/**
	 * 读取自增值。如果对数据实时性要求高，可改为从写模式下读取数据；或者通过increment方法返回数据。
	 * @param  string $key      缓存的key
	 * @return mixed  返回key对应的value，
	 *    如果结果不存在、过期或者在获取的过程中发生错误，将会返回false. 
	 */
	public function readIncrement($key) {
		$conn = $this->connect(CacheTtserver::ALONE_TYPE_READ);
		return $conn->get($key);
	}


	public function flush() {
		$conn = $this->connect(CacheTtserver::ALONE_TYPE_WRITE);
		$conn->flush();
		$conn = $this->connect(CacheTtserver::ALONE_TYPE_READ);
		$conn->flush();
	}


	public function getStats() {
		//echo 'connections:';
		//print_r($this->connection);
		if(is_array($this->connection)) {
			foreach($this->connection as $k=>$v) {
				print_r($v->getStats());
			}
		} else {
			if(!empty($this->connection))
				print_r($this->connection->getStats());
		}//*/
	}

	public function __destruct() {
		$this->connection = null;
	}

	protected function _debug($s) {
		//if($this->bDebug || defined("__MOD_DEBUG_TEST")) {
		if(defined("__MOD_DEBUG_TEST")) {
			print_r($s);
			echo '<br>';
		}
	}

	protected function getdebug($errno){
		global $error_object;

		echo $msg = $error_object->getErrorMsg($errno);exit;
	}
}

/*
require_once('Ttserver.config.php');
require_once('CacheTtserver.class.php');
$mem = new CacheTtserver();
$a = array(
	'user_1'=>array('a'=>1,'b'=>'abv123','c'=>array('a','b'))
	,'user_2'=>array('a'=>2,'b'=>'zz234','c'=>array('1','23'))
);
foreach($a as $k=>$v) {
	$mem->write($k, $v, 60);
}
$d = $mem->read(array_keys($a));
var_dump( $d );

$mem2 = new CacheTtserver();
$mem2->setServers($aServers);
foreach($a as $k=>$v) {
	$mem2->write($k, $v, 60);
}
$d = $mem2->read(array_keys($a));
var_dump( $d );
*/

?>